#include <iostream>
using namespace std;
#include <cstring>

/*
     初始化列表
     初始化列表 -一定是放在构造函数中,
     必须要使用初始化列表的两种情况:
     1.有const修饰的成员属性(成员变量)
     2.当一个类(A类)中包含了其他类(c类)，并且这个c类要有 有参构造函数。
     3,(构造函数相互调用的时候，会产生临时对象，所以需要放到初始化列表里面:)
2
*/

class Person
{

public:
    // Person(int age,char sex,char*name)
    // {
    //     /*函数体*/
    //     m_age=age;
    //     m_sex=sex;
    //     strcpy(m_name,name);
    // }
    /*使用初始化列表的方式 */
    Person(int age, char sex, char *name) : m_age(age), msex(sex)
    {
        strcpy(m_name, name);
    }

private:
    /*年龄*/
    int m_age;
    /*性别*/
    char m_sex;
    /*姓名 */
    char m_name[20];
};

class Student
{
private:
    /* data */
public:
    Student(/* args */);
    ~Student();

public:
    /*年龄 */
    int m_age;
    /*性别 */
    char m_sex;
    /*姓名 */
    char m_name[20];

    /*学号*/
    int m_stuId;
    /*考试分数 */
    int m_score;
};

/*继承的语法*/
/*
    继承:被继承的类被称为父类(基类)
    继承的类被称为子类(派生类)
    访问权限不影响对象的内存布局
*/
class Employee : public Person
{
public:
    /*工号*/
    int jobId;
    /*薪资*/
    int salary;
};

/*
07.父类的构造函数
    1. 子类的构造函数默认会调用父类的无参构造函数
    2. 如果子类的构造函数显式地调用了父类的有参构造函数,就不会再去默认调用父类的无参构造函数
    3. 如果父类缺少无参构造函数，子类的构造函数必须显式调用父类的有参构造函数
*/

class Animal
{
public:
    Animal(int age = 0, char sex ='m') : m_age(age), m_sex(sex)
    {
    }

public:
    void show()
    {
        cout << "age:" << m_age << "sex:" << m_sex << endl;
    }

private:
    int m_age;
    int m_sex;
};

/*6,构造函数的互相调用*/
class DyArray
{

public:
    // 无参构造
    DyArray()
    {
        DyArray(10);
    }

    // 有参构造
    DyArray(int capacity)
    {
        // 容量
        m_capacity = capacity;
        /* 分配空间 */
        m_data = new int[m_capacity];
        /*清除脏数据*/
        memset(m_data, 0, sizeof(int) * m_capacity);
    }

private:
    int m_capacity;
    int *m_data;
};

class TrafficTool
{
private:
    /* 轮子数 */
    int m_wheels;
    /*颜色*/
    string m_color;

public:
    TrafficTool(/* args */);
    ~TrafficTool();
};

/*8,
    子类继承父类:
        构造函数:  先调用父类的构造函数，再调用子类的构造函数
        析构函数:  先调用子类的析构函数, 再调用父类的析构函数
*/

// class Car : public TrafficTool
// {
// private:
//     /* data */
// public:
//     Car : public TrafficTool(/* args */);
//     ~Car : public TrafficTool();
// };

/*9.父类指针 & 子类指针*/
/*植物类*/
class Plant
{
public:
    /*年份 */
    int m_age;

};

/*向日葵类 */
class Sunflower : public Plant
{
public:
    /*高度 */
    int m_height;
};


/*菱形继承*/
class Grand
{

public:
    int m_a;
};





int main()
{
#if 0
    Person per1;
    /*赋值*/
    per1.m_age = 21;
    per1.m_sex = 'f';
    strcpy(per1.m_name, "zhangsan");

    /*打印 */
    cout << "age:"<< per1.m_age << endl;
    cout << "sex:" <<per1.m_sex << endl;
    cout << "name:" << per1.m_name << endl;

    Student stu1;
    stu1.m_age = 22;
    stu1.m_sex = 'm';
    strcpy(stu1.m_name, "lisi");
    stu1.m_stuId = 43639;
    stu1.m_score = 90;

#endif

#if 0
    Employee emp1;
    emp1.m_age = 30;
    strcpy(emp1.m_name, "wangwu");
    emp1.m_sex = 'm';
    emp1.jobId = 56732;
    emp1.salary = 23000;

    /*打印 */
    cout << "age:" << emp1.m_age << endl;
    cout << "sex:" << emp1.m_sex << endl;
    cout << "name:" << emp1.m_name << endl;
    cout << "jobId:" << emp1.jobId << endl;
    cout << "salary:" << emp1.salary << endl;

    /*2.对象的内存布局 */
    /*子类继承父类的时候，子类会继承父类的所有信息。那么子类的内存大小是子类的属性 + 父类的属性。*/
    int size = sizeof(emp1);
    cout << "size:" << size << endl;
    cout << "&age:" << &(emp1.m_age) << endl;
    printf("&sex:%p\n", &(emp1.m_sex));
    printf("name:%p\n", emp1.m_name);
    cout << "&jobId:" << &(emp1.jobId) << endl;
    cout << "&salary:" << &(emp1.salary) << endl;
#endif

#if 0

    /*  成员访问权限、继承方式有3种
        public:公共的，任何地方都可以访问(struct默认)
        protected:子类内部、当前类内部可以访问
        private:私有的，只有当前类内部可以访问(class 默认)
        子类内部访问父类成员的权限,是以下2项中权限最小的那个
        1,成员本身的访问权限
        2,继承父类的方式
        开发中用的最多的继承方式是 public,这样能保留父类原来的成员访问权限
        ***访问权限不影响对象的内存布局
    */

    /*访问权限 */
    Employee emp1;
    emp1.jobId = 43639;

#endif

#if 1
    /*植物类*/
    Plant *mplant = new Plant;
    mplant->m_age = 10;
    cout << mplant->m_age << endl;
    /*向日葵类*/
    Sunflower *msunFlw = new Sunflower;
    msunFlw->m_age = 5;
    msunFlw->m_height = 130;
    cout << "age:" << msunFlw->m_age << ",height:" << msunFlw->m_height << endl;

    /*子类指针指向子类对象*/
    Plant *mplant2 = new Sunflower;
    mplant2->m_age = 6;
    cout << mplant2->m_age << endl;

    /*子类指针指向父类对象 */
    Sunflower *msunFlw2 = new Plant;
    msunFlw2->m_age = 7;
    msunFlw2->m_height = 145;

#endif

    return 0;
}